
// --========================================================================--
//  This confidential and proprietary software may be used only as
//  authorised by a licensing agreement from ARM Limited
//    (C) COPYRIGHT 2005-2013 ARM Limited
//        ALL RIGHTS RESERVED
//  The entire notice above must be reproduced on all authorised
//  copies and copies may only be made to the extent permitted
//  by a licensing agreement from ARM Limited.
// -----------------------------------------------------------------------------
//
//  Version and Release Control Information:
//
//  File Revision          : 149902
//  File Date              :  2013-05-08 18:20:26 +0100 (Wed, 08 May 2013)
//
//  Release Information    : PL401-r0p1-00eac0
//
// -----------------------------------------------------------------------------

// -----------------------------------------------------------------------------
// Purpose: Clock and Reset Interface
//
// This block generates the clock and reset signals
//
// The generation logic can be controlled via the APB interface, which has the
// following programmers interface:
//
// Each clock_domain has one register where:
//
// [7:0] clock divisor
// [15:8] offset
// [16] reset_n bit
// [17] reset bit
//
//
// NB This block will only update clock periods on the rising edge of the clock
//    NB THIS BLOCK IS APB3
// --=========================================================================--

`timescale 1ns/1ps

module clk_reset_if
  (

   //Signals for each clock

   clk_peri_25mclk,
   clk_peri_25mclk_tb,
   clk_peri_25mresetn,
   clk_peri_25mclk_r,
   clk_peri_25mresetn_r,
   clk_peri_25men,
   clk_peri_25men_apb,

   clk_peri_100mclk,
   clk_peri_100mclk_tb,
   clk_peri_100mresetn,
   clk_peri_100mclk_r,
   clk_peri_100mresetn_r,
   clk_peri_100men,
   clk_peri_100men_apb,

   clk_core_200_800mclk,
   clk_core_200_800mclk_tb,
   clk_core_200_800mresetn,
   clk_core_200_800mclk_r,
   clk_core_200_800mresetn_r,
   clk_core_200_800men,
   clk_core_200_800men_apb,

   clk_aud_12288kclk,
   clk_aud_12288kclk_tb,
   clk_aud_12288kresetn,
   clk_aud_12288ken,
   clk_aud_12288ken_apb,


   //Global TB clocks
   clk_tb,
   resetn_tb,

   //APB programming interface
   prdata,
   pready,
   psel,
   penable,
   pslverr,
   pwrite,
   paddr,
   pwdata
  );

  // Clock and Resets

  output       clk_peri_25mclk;
  output       clk_peri_25mclk_tb;
  output       clk_peri_25mresetn;
  output       clk_peri_25mclk_r;
  output       clk_peri_25mresetn_r;
  output       clk_peri_25men;
  output       clk_peri_25men_apb;

  output       clk_peri_100mclk;
  output       clk_peri_100mclk_tb;
  output       clk_peri_100mresetn;
  output       clk_peri_100mclk_r;
  output       clk_peri_100mresetn_r;
  output       clk_peri_100men;
  output       clk_peri_100men_apb;

  output       clk_core_200_800mclk;
  output       clk_core_200_800mclk_tb;
  output       clk_core_200_800mresetn;
  output       clk_core_200_800mclk_r;
  output       clk_core_200_800mresetn_r;
  output       clk_core_200_800men;
  output       clk_core_200_800men_apb;

  output       clk_aud_12288kclk;
  output       clk_aud_12288kclk_tb;
  output       clk_aud_12288kresetn;
  output       clk_aud_12288ken;
  output       clk_aud_12288ken_apb;


  // Global resets
  output        clk_tb;
  output        resetn_tb;

  // APB3 Block Interface
  output [31:0] prdata;
  output        pready;
  input         psel;
  input         penable;
  input         pwrite;
  input [31:0]  paddr;
  input [31:0]  pwdata;
  output        pslverr;

//------------------------------------------------------------------------------
// Constants
//------------------------------------------------------------------------------
// PSEL decoding is done using bits [15:12], so look at [11:0] here
`define CLK_REG0       12'd0       // Register 0 Offset

`define CLK_REG1       12'd4       // Register 1 Offset
`define CLK_REG1_INIT  32'h00000000  // Initial Value

`define CLK_REG2       12'd8       // Register 2 Offset
`define CLK_REG2_INIT  32'h00000000  // Initial Value

`define CLK_REG3       12'd12       // Register 3 Offset
`define CLK_REG3_INIT  32'h00000000  // Initial Value

`define CLK_REG4       12'd16       // Register 4 Offset
`define CLK_REG4_INIT  32'h00000000  // Initial Value


`define INT_CLK_PERIOD 50 // Internal Clock Period


//------------------------------------------------------------------------------
// Registers
//------------------------------------------------------------------------------
  // Clock and Reset in AXI domain
  reg           int_clk_i;
  reg           int_resetn_init;


  // Used in generation of reset
  integer       i;


  reg          clk_peri_25mclk;
  reg          clk_peri_25mclk_tb;
  reg          clk_peri_25mclk_r;
  reg          clk_peri_25mresetn;
  reg          clk_peri_25mresetn_r;

  reg          clk_peri_100mclk;
  reg          clk_peri_100mclk_tb;
  reg          clk_peri_100mclk_r;
  reg          clk_peri_100mresetn;
  reg          clk_peri_100mresetn_r;

  reg          clk_core_200_800mclk;
  reg          clk_core_200_800mclk_tb;
  reg          clk_core_200_800mclk_r;
  reg          clk_core_200_800mresetn;
  reg          clk_core_200_800mresetn_r;

  reg          clk_aud_12288kclk;
  reg          clk_aud_12288kclk_tb;
  reg          clk_aud_12288kresetn;


//------------------------------------------------------------------------------
// Wires
//------------------------------------------------------------------------------
  //shared write signals
  wire          enable;
  reg [31:0]    prdata;




  // APB write decode
  wire          def_reg_wr;

  wire          reg_clk_peri_25m_wr;
  reg [31:0]    reg_clk_peri_25m;

  reg  [7:0]    clk_peri_25m_count;
  wire [7:0]    clk_peri_25m_count_next;
  wire [7:0]    clk_peri_25m_ratio;
  wire [7:0]    clk_peri_25m_ratio_in;
  wire [7:0]    clk_peri_25m_en_ratio;
  reg  [7:0]    clk_peri_25m_en_count;

  reg           clk_peri_25mclk_int;
  reg           clk_peri_25mresetn_init;
  wire          assert_clk_peri_25mresetn;
  wire          assert_clk_peri_25mresetn_r;
  reg           deassert_clk_peri_25mresetn;
  reg           deassert_clk_peri_25mresetn_r;
  wire          clk_peri_25m_update;
  wire          clk_peri_25m_up_del;
  wire          clk_peri_25m_up_or;
  wire          clk_peri_25men_del;
  wire          clk_peri_25men_apb_a;
  wire          clk_peri_25men_apb_z;
  wire          reg_clk_peri_100m_wr;
  reg [31:0]    reg_clk_peri_100m;

  reg  [7:0]    clk_peri_100m_count;
  wire [7:0]    clk_peri_100m_count_next;
  wire [7:0]    clk_peri_100m_ratio;
  wire [7:0]    clk_peri_100m_ratio_in;
  wire [7:0]    clk_peri_100m_en_ratio;
  reg  [7:0]    clk_peri_100m_en_count;

  reg           clk_peri_100mclk_int;
  reg           clk_peri_100mresetn_init;
  wire          assert_clk_peri_100mresetn;
  wire          assert_clk_peri_100mresetn_r;
  reg           deassert_clk_peri_100mresetn;
  reg           deassert_clk_peri_100mresetn_r;
  wire          clk_peri_100m_update;
  wire          clk_peri_100m_up_del;
  wire          clk_peri_100m_up_or;
  wire          clk_peri_100men_del;
  wire          clk_peri_100men_apb_a;
  wire          clk_peri_100men_apb_z;
  wire          reg_clk_core_200_800m_wr;
  reg [31:0]    reg_clk_core_200_800m;

  reg  [7:0]    clk_core_200_800m_count;
  wire [7:0]    clk_core_200_800m_count_next;
  wire [7:0]    clk_core_200_800m_ratio;
  wire [7:0]    clk_core_200_800m_ratio_in;
  wire [7:0]    clk_core_200_800m_en_ratio;
  reg  [7:0]    clk_core_200_800m_en_count;

  reg           clk_core_200_800mclk_int;
  reg           clk_core_200_800mresetn_init;
  wire          assert_clk_core_200_800mresetn;
  wire          assert_clk_core_200_800mresetn_r;
  reg           deassert_clk_core_200_800mresetn;
  reg           deassert_clk_core_200_800mresetn_r;
  wire          clk_core_200_800m_update;
  wire          clk_core_200_800m_up_del;
  wire          clk_core_200_800m_up_or;
  wire          clk_core_200_800men_del;
  wire          clk_core_200_800men_apb_a;
  wire          clk_core_200_800men_apb_z;
  wire          reg_clk_aud_12288k_wr;
  reg [31:0]    reg_clk_aud_12288k;

  reg  [7:0]    clk_aud_12288k_count;
  wire [7:0]    clk_aud_12288k_count_next;
  wire [7:0]    clk_aud_12288k_ratio;
  wire [7:0]    clk_aud_12288k_ratio_in;
  wire [7:0]    clk_aud_12288k_en_ratio;
  reg  [7:0]    clk_aud_12288k_en_count;

  reg           clk_aud_12288kclk_int;
  reg           clk_aud_12288kresetn_init;
  wire          assert_clk_aud_12288kresetn;
  reg           deassert_clk_aud_12288kresetn;
  wire          clk_aud_12288k_update;
  wire          clk_aud_12288k_up_del;
  wire          clk_aud_12288k_up_or;
  wire          clk_aud_12288ken_del;
  wire          clk_aud_12288ken_apb_a;
  wire          clk_aud_12288ken_apb_z;

  wire          default_slave;
  reg [8:0]     count;
  wire [8:0]    next_count;
  reg           cgen_reset;
  reg           clk_tb;
  reg           resetn_tb_init;
  reg  [4:0]     clk_stop_reg;
  reg           rclk_stop_reg;
  wire [4:0]     clk_stop;
  wire           rclk_stop;
  reg           disable_clk_gate_reg;
  wire          disable_clk_gate;

 

//------------------------------------------------------------------------------
// APB write logic
//------------------------------------------------------------------------------
// Revisit add terms
  always@(psel or penable or paddr or pwrite 
          or reg_clk_peri_25m
          or reg_clk_peri_100m
          or reg_clk_core_200_800m
          or reg_clk_aud_12288k) begin
    prdata = 32'b0;
    if(psel && penable)
      case(paddr[11:0])
       `CLK_REG1 : prdata = reg_clk_peri_25m;
       `CLK_REG2 : prdata = reg_clk_peri_100m;
       `CLK_REG3 : prdata = reg_clk_core_200_800m;
       `CLK_REG4 : prdata = reg_clk_aud_12288k;
       default   : prdata = 32'd0;
      endcase
  end

  //PREADY is held low while enable is high and no wr signal is accepted
  assign default_slave = enable &
                         (paddr[11:0] != `CLK_REG0
                          & paddr[11:0] != `CLK_REG1
                          & paddr[11:0] != `CLK_REG2
                          & paddr[11:0] != `CLK_REG3
                          & paddr[11:0] != `CLK_REG4
                         );

  assign pready = ~enable | def_reg_wr | reg_clk_peri_25m_wr |reg_clk_peri_100m_wr |reg_clk_core_200_800m_wr |reg_clk_aud_12288k_wr |default_slave;


  assign enable = (psel & pwrite & penable);

  assign pslverr = 1'b0;


  assign def_reg_wr = (paddr[11:0] == `CLK_REG0) & enable;

  always @ (posedge clk_tb or negedge int_resetn_init) begin
    if (!int_resetn_init) begin
        clk_stop_reg         <= 32'b0;
        rclk_stop_reg        <= 1'b0;
        disable_clk_gate_reg <= 1'b0;
    end else if (def_reg_wr) begin
        clk_stop_reg         <= pwdata[0];
        rclk_stop_reg        <= pwdata[1];
        disable_clk_gate_reg <= pwdata[2];
    end
  end

  assign clk_stop         =  clk_stop_reg;
  assign rclk_stop        =  rclk_stop_reg;
  assign disable_clk_gate = disable_clk_gate_reg | clk_stop[4];


  assign reg_clk_peri_25m_wr = (paddr[11:0] == `CLK_REG1) & enable;

  always @ (posedge clk_tb or negedge int_resetn_init) begin
    if (!int_resetn_init) begin
      reg_clk_peri_25m <= `CLK_REG1_INIT;
    end else if (reg_clk_peri_25m_wr) begin
      reg_clk_peri_25m <= pwdata;
    end else if (def_reg_wr) begin
       reg_clk_peri_25m[17:16] <= pwdata[17:16];
    end
  end

  assign reg_clk_peri_100m_wr = (paddr[11:0] == `CLK_REG2) & enable;

  always @ (posedge clk_tb or negedge int_resetn_init) begin
    if (!int_resetn_init) begin
      reg_clk_peri_100m <= `CLK_REG2_INIT;
    end else if (reg_clk_peri_100m_wr) begin
      reg_clk_peri_100m <= pwdata;
    end else if (def_reg_wr) begin
       reg_clk_peri_100m[17:16] <= pwdata[17:16];
    end
  end

  assign reg_clk_core_200_800m_wr = (paddr[11:0] == `CLK_REG3) & enable;

  always @ (posedge clk_tb or negedge int_resetn_init) begin
    if (!int_resetn_init) begin
      reg_clk_core_200_800m <= `CLK_REG3_INIT;
    end else if (reg_clk_core_200_800m_wr) begin
      reg_clk_core_200_800m <= pwdata;
    end else if (def_reg_wr) begin
       reg_clk_core_200_800m[17:16] <= pwdata[17:16];
    end
  end

  assign reg_clk_aud_12288k_wr = (paddr[11:0] == `CLK_REG4) & enable;

  always @ (posedge clk_tb or negedge int_resetn_init) begin
    if (!int_resetn_init) begin
      reg_clk_aud_12288k <= `CLK_REG4_INIT;
    end else if (reg_clk_aud_12288k_wr) begin
      reg_clk_aud_12288k <= pwdata;
    end else if (def_reg_wr) begin
       reg_clk_aud_12288k[17:16] <= pwdata[17:16];
    end
  end


//------------------------------------------------------------------------------
// Initial Clock and Reset Generation
//------------------------------------------------------------------------------

  initial
    begin
      int_clk_i  = 1'b1;
    end

  // Generate internal clock
  always
    begin
       #`INT_CLK_PERIOD int_clk_i  <= ~int_clk_i;
    end

  // Hold reset low initially for 10 cycles
  initial
    begin
      int_resetn_init = 0;
      for (i = 0; i < 10; i = i + 1)
        @(int_clk_i);
      int_resetn_init = 1;
    end

  // Hold cgen_reset low initially for 1 ns
  initial
    begin
      cgen_reset = 1'b1;
      #1 cgen_reset = 1'b0;
      #1 cgen_reset = 1'b1;
    end

   always@(posedge clk_tb) begin
      begin
         resetn_tb_init <= int_resetn_init;
      end
   end

  //Assign resetn_tb
  assign resetn_tb = resetn_tb_init & int_resetn_init;

//------------------------------------------------------------------------------
// Reset Generation
//------------------------------------------------------------------------------



   assign assert_clk_peri_25mresetn   = ~reg_clk_peri_25m[17];
   assign assert_clk_peri_25mresetn_r = ~reg_clk_peri_25m[16];

   always@(posedge clk_peri_25mclk_int or negedge cgen_reset) begin
      if (!cgen_reset) begin
         deassert_clk_peri_25mresetn   <= 1'b1;
         deassert_clk_peri_25mresetn_r <= 1'b1;
      end else begin
         deassert_clk_peri_25mresetn   <= assert_clk_peri_25mresetn;
         deassert_clk_peri_25mresetn_r <= assert_clk_peri_25mresetn_r;
      end
   end

   always@(posedge clk_peri_25mclk_int) begin
      begin
         clk_peri_25mresetn_init <= int_resetn_init;
      end
   end

   initial
      begin
         clk_peri_25mresetn   = 1'b0;
         clk_peri_25mresetn_r = 1'b0;
      end

   always@(assert_clk_peri_25mresetn   or deassert_clk_peri_25mresetn   or clk_peri_25mresetn_init or int_resetn_init)
      begin
         clk_peri_25mresetn   = assert_clk_peri_25mresetn   & deassert_clk_peri_25mresetn   & clk_peri_25mresetn_init & int_resetn_init;
      end

   always@(assert_clk_peri_25mresetn_r or deassert_clk_peri_25mresetn_r or clk_peri_25mresetn_init or int_resetn_init)
      begin
         clk_peri_25mresetn_r = assert_clk_peri_25mresetn_r & deassert_clk_peri_25mresetn_r & clk_peri_25mresetn_init & int_resetn_init;
      end

     
   assign assert_clk_peri_100mresetn   = ~reg_clk_peri_100m[17];
   assign assert_clk_peri_100mresetn_r = ~reg_clk_peri_100m[16];

   always@(posedge clk_peri_100mclk_int or negedge cgen_reset) begin
      if (!cgen_reset) begin
         deassert_clk_peri_100mresetn   <= 1'b1;
         deassert_clk_peri_100mresetn_r <= 1'b1;
      end else begin
         deassert_clk_peri_100mresetn   <= assert_clk_peri_100mresetn;
         deassert_clk_peri_100mresetn_r <= assert_clk_peri_100mresetn_r;
      end
   end

   always@(posedge clk_peri_100mclk_int) begin
      begin
         clk_peri_100mresetn_init <= int_resetn_init;
      end
   end

   initial
      begin
         clk_peri_100mresetn   = 1'b0;
         clk_peri_100mresetn_r = 1'b0;
      end

   always@(assert_clk_peri_100mresetn   or deassert_clk_peri_100mresetn   or clk_peri_100mresetn_init or int_resetn_init)
      begin
         clk_peri_100mresetn   = assert_clk_peri_100mresetn   & deassert_clk_peri_100mresetn   & clk_peri_100mresetn_init & int_resetn_init;
      end

   always@(assert_clk_peri_100mresetn_r or deassert_clk_peri_100mresetn_r or clk_peri_100mresetn_init or int_resetn_init)
      begin
         clk_peri_100mresetn_r = assert_clk_peri_100mresetn_r & deassert_clk_peri_100mresetn_r & clk_peri_100mresetn_init & int_resetn_init;
      end

     
   assign assert_clk_core_200_800mresetn   = ~reg_clk_core_200_800m[17];
   assign assert_clk_core_200_800mresetn_r = ~reg_clk_core_200_800m[16];

   always@(posedge clk_core_200_800mclk_int or negedge cgen_reset) begin
      if (!cgen_reset) begin
         deassert_clk_core_200_800mresetn   <= 1'b1;
         deassert_clk_core_200_800mresetn_r <= 1'b1;
      end else begin
         deassert_clk_core_200_800mresetn   <= assert_clk_core_200_800mresetn;
         deassert_clk_core_200_800mresetn_r <= assert_clk_core_200_800mresetn_r;
      end
   end

   always@(posedge clk_core_200_800mclk_int) begin
      begin
         clk_core_200_800mresetn_init <= int_resetn_init;
      end
   end

   initial
      begin
         clk_core_200_800mresetn   = 1'b0;
         clk_core_200_800mresetn_r = 1'b0;
      end

   always@(assert_clk_core_200_800mresetn   or deassert_clk_core_200_800mresetn   or clk_core_200_800mresetn_init or int_resetn_init)
      begin
         clk_core_200_800mresetn   = assert_clk_core_200_800mresetn   & deassert_clk_core_200_800mresetn   & clk_core_200_800mresetn_init & int_resetn_init;
      end

   always@(assert_clk_core_200_800mresetn_r or deassert_clk_core_200_800mresetn_r or clk_core_200_800mresetn_init or int_resetn_init)
      begin
         clk_core_200_800mresetn_r = assert_clk_core_200_800mresetn_r & deassert_clk_core_200_800mresetn_r & clk_core_200_800mresetn_init & int_resetn_init;
      end

     

   assign assert_clk_aud_12288kresetn   = ~reg_clk_aud_12288k[17];

   always@(posedge clk_aud_12288kclk_int or negedge cgen_reset) begin
      if (!cgen_reset) begin
         deassert_clk_aud_12288kresetn   <= 1'b1;
      end else begin
         deassert_clk_aud_12288kresetn   <= assert_clk_aud_12288kresetn;
      end
   end

   always@(posedge clk_aud_12288kclk_int) begin
      begin
         clk_aud_12288kresetn_init <= int_resetn_init;
      end
   end

   initial
      begin
         clk_aud_12288kresetn   = 1'b0;
      end

   always@(assert_clk_aud_12288kresetn   or deassert_clk_aud_12288kresetn   or clk_aud_12288kresetn_init or int_resetn_init)
      begin
         clk_aud_12288kresetn   = assert_clk_aud_12288kresetn   & deassert_clk_aud_12288kresetn   & clk_aud_12288kresetn_init & int_resetn_init;
      end


//------------------------------------------------------------------------------
// Clock Generation
//------------------------------------------------------------------------------
  always@(posedge int_clk_i or negedge cgen_reset) begin
      if (!cgen_reset) begin
         clk_peri_25mclk_int   <= 1'b0;
         clk_peri_25mclk       <= 1'b0;
         clk_peri_25mclk_r     <= 1'b0;
         clk_peri_25mclk_tb    <= 1'b0;
         clk_peri_100mclk_int   <= 1'b0;
         clk_peri_100mclk       <= 1'b0;
         clk_peri_100mclk_r     <= 1'b0;
         clk_peri_100mclk_tb    <= 1'b0;
         clk_core_200_800mclk_int   <= 1'b0;
         clk_core_200_800mclk       <= 1'b0;
         clk_core_200_800mclk_r     <= 1'b0;
         clk_core_200_800mclk_tb    <= 1'b0;
         clk_aud_12288kclk_int   <= 1'b0;
         clk_aud_12288kclk       <= 1'b0;
         clk_aud_12288kclk_tb    <= 1'b0;
         
         count <= 9'h00;
         clk_tb  <= 1'b0;
      end else begin
         clk_tb  <= ~clk_tb;
         count <= next_count;
         
         if (~clk_stop[0] || ~clk_peri_25mresetn) begin
             clk_peri_25mclk_int   <= clk_peri_25m_update;
             clk_peri_25mclk       <= clk_peri_25m_update;
             clk_peri_25mclk_r     <= clk_peri_25m_update;
             
         end
         clk_peri_25mclk_tb    <= clk_peri_25m_update;
         
         if (~clk_stop[1] || ~clk_peri_100mresetn) begin
             clk_peri_100mclk_int   <= clk_peri_100m_update;
             clk_peri_100mclk       <= clk_peri_100m_update;
             clk_peri_100mclk_r     <= clk_peri_100m_update;
             
         end
         clk_peri_100mclk_tb    <= clk_peri_100m_update;
         
         if (~clk_stop[2] || ~clk_core_200_800mresetn) begin
             clk_core_200_800mclk_int   <= clk_core_200_800m_update;
             clk_core_200_800mclk       <= clk_core_200_800m_update;
             clk_core_200_800mclk_r     <= clk_core_200_800m_update;
             
         end
         clk_core_200_800mclk_tb    <= clk_core_200_800m_update;
         clk_aud_12288kclk_int   <= clk_aud_12288k_update;
         clk_aud_12288kclk       <= clk_aud_12288k_update;
         clk_aud_12288kclk_tb    <= clk_aud_12288k_update;
         
      end
  end

  assign next_count = count + 9'b1;


  assign clk_peri_25m_update = ({clk_peri_25m_count, 1'b1} == next_count);

  // Generate aclk from register ratio
  always@(posedge int_clk_i or negedge cgen_reset) begin
    if (!cgen_reset)
      clk_peri_25m_count <= 1'b0;
    else if (clk_peri_25m_update)
      clk_peri_25m_count <= next_count[8:1] + clk_peri_25m_ratio;
    else if (reg_clk_peri_25m_wr)
      //Load with the next alligned count value
      clk_peri_25m_count <= count[8:1] + clk_peri_25m_count_next + pwdata[15:8];
  end

  assign clk_peri_25m_count_next = clk_peri_25m_ratio_in - (count[8:1] % clk_peri_25m_ratio_in);

  //Create ENABLE to divide CLK
  always@(posedge clk_peri_25mclk_int or negedge cgen_reset) begin
    if (!cgen_reset)
      clk_peri_25m_en_count <= 8'h01;
    else if ((clk_peri_25m_en_count == clk_peri_25m_en_ratio) || reg_clk_peri_25m_wr || (clk_peri_25m_en_ratio == 8'h01))
      clk_peri_25m_en_count <= 8'h01;
    else if (clk_peri_25m_en_ratio != 8'h01)
      clk_peri_25m_en_count <= clk_peri_25m_en_count + 8'h01;
  end

  assign clk_peri_25m_offset_diff = {8{reg_clk_peri_25m_wr}} & (pwdata[15:8] - reg_clk_peri_25m[15:8]);

  assign clk_peri_25m_ratio = (|reg_clk_peri_25m[7:0]) ? reg_clk_peri_25m[7:0] : 8'b00000001;
  assign clk_peri_25m_ratio_in = (|pwdata[7:0]) ? pwdata[7:0] : 8'b00000001;
  assign clk_peri_25m_en_ratio = (|reg_clk_peri_25m[25:18]) ? reg_clk_peri_25m[25:18] : 8'b00000001;
  assign #2 clk_peri_25m_up_del = clk_peri_25m_update;
  assign clk_peri_25m_up_or = clk_peri_25m_update | clk_peri_25m_up_del;
  assign clk_peri_25men = clk_peri_25m_up_or;
  assign clk_peri_25men_del = clk_peri_25m_up_del;
  assign clk_peri_25men_apb_a = (clk_peri_25m_en_count == clk_peri_25m_en_ratio) & clk_peri_25m_update;
  assign #2 clk_peri_25men_apb_z = clk_peri_25men_apb_a;
  assign clk_peri_25men_apb = clk_peri_25men_apb_a | clk_peri_25men_apb_z;

  assign clk_peri_100m_update = ({clk_peri_100m_count, 1'b1} == next_count);

  // Generate aclk from register ratio
  always@(posedge int_clk_i or negedge cgen_reset) begin
    if (!cgen_reset)
      clk_peri_100m_count <= 1'b0;
    else if (clk_peri_100m_update)
      clk_peri_100m_count <= next_count[8:1] + clk_peri_100m_ratio;
    else if (reg_clk_peri_100m_wr)
      //Load with the next alligned count value
      clk_peri_100m_count <= count[8:1] + clk_peri_100m_count_next + pwdata[15:8];
  end

  assign clk_peri_100m_count_next = clk_peri_100m_ratio_in - (count[8:1] % clk_peri_100m_ratio_in);

  //Create ENABLE to divide CLK
  always@(posedge clk_peri_100mclk_int or negedge cgen_reset) begin
    if (!cgen_reset)
      clk_peri_100m_en_count <= 8'h01;
    else if ((clk_peri_100m_en_count == clk_peri_100m_en_ratio) || reg_clk_peri_100m_wr || (clk_peri_100m_en_ratio == 8'h01))
      clk_peri_100m_en_count <= 8'h01;
    else if (clk_peri_100m_en_ratio != 8'h01)
      clk_peri_100m_en_count <= clk_peri_100m_en_count + 8'h01;
  end

  assign clk_peri_100m_offset_diff = {8{reg_clk_peri_100m_wr}} & (pwdata[15:8] - reg_clk_peri_100m[15:8]);

  assign clk_peri_100m_ratio = (|reg_clk_peri_100m[7:0]) ? reg_clk_peri_100m[7:0] : 8'b00000001;
  assign clk_peri_100m_ratio_in = (|pwdata[7:0]) ? pwdata[7:0] : 8'b00000001;
  assign clk_peri_100m_en_ratio = (|reg_clk_peri_100m[25:18]) ? reg_clk_peri_100m[25:18] : 8'b00000001;
  assign #2 clk_peri_100m_up_del = clk_peri_100m_update;
  assign clk_peri_100m_up_or = clk_peri_100m_update | clk_peri_100m_up_del;
  assign clk_peri_100men = clk_peri_100m_up_or;
  assign clk_peri_100men_del = clk_peri_100m_up_del;
  assign clk_peri_100men_apb_a = (clk_peri_100m_en_count == clk_peri_100m_en_ratio) & clk_peri_100m_update;
  assign #2 clk_peri_100men_apb_z = clk_peri_100men_apb_a;
  assign clk_peri_100men_apb = clk_peri_100men_apb_a | clk_peri_100men_apb_z;

  assign clk_core_200_800m_update = ({clk_core_200_800m_count, 1'b1} == next_count);

  // Generate aclk from register ratio
  always@(posedge int_clk_i or negedge cgen_reset) begin
    if (!cgen_reset)
      clk_core_200_800m_count <= 1'b0;
    else if (clk_core_200_800m_update)
      clk_core_200_800m_count <= next_count[8:1] + clk_core_200_800m_ratio;
    else if (reg_clk_core_200_800m_wr)
      //Load with the next alligned count value
      clk_core_200_800m_count <= count[8:1] + clk_core_200_800m_count_next + pwdata[15:8];
  end

  assign clk_core_200_800m_count_next = clk_core_200_800m_ratio_in - (count[8:1] % clk_core_200_800m_ratio_in);

  //Create ENABLE to divide CLK
  always@(posedge clk_core_200_800mclk_int or negedge cgen_reset) begin
    if (!cgen_reset)
      clk_core_200_800m_en_count <= 8'h01;
    else if ((clk_core_200_800m_en_count == clk_core_200_800m_en_ratio) || reg_clk_core_200_800m_wr || (clk_core_200_800m_en_ratio == 8'h01))
      clk_core_200_800m_en_count <= 8'h01;
    else if (clk_core_200_800m_en_ratio != 8'h01)
      clk_core_200_800m_en_count <= clk_core_200_800m_en_count + 8'h01;
  end

  assign clk_core_200_800m_offset_diff = {8{reg_clk_core_200_800m_wr}} & (pwdata[15:8] - reg_clk_core_200_800m[15:8]);

  assign clk_core_200_800m_ratio = (|reg_clk_core_200_800m[7:0]) ? reg_clk_core_200_800m[7:0] : 8'b00000001;
  assign clk_core_200_800m_ratio_in = (|pwdata[7:0]) ? pwdata[7:0] : 8'b00000001;
  assign clk_core_200_800m_en_ratio = (|reg_clk_core_200_800m[25:18]) ? reg_clk_core_200_800m[25:18] : 8'b00000001;
  assign #2 clk_core_200_800m_up_del = clk_core_200_800m_update;
  assign clk_core_200_800m_up_or = clk_core_200_800m_update | clk_core_200_800m_up_del;
  assign clk_core_200_800men = clk_core_200_800m_up_or;
  assign clk_core_200_800men_del = clk_core_200_800m_up_del;
  assign clk_core_200_800men_apb_a = (clk_core_200_800m_en_count == clk_core_200_800m_en_ratio) & clk_core_200_800m_update;
  assign #2 clk_core_200_800men_apb_z = clk_core_200_800men_apb_a;
  assign clk_core_200_800men_apb = clk_core_200_800men_apb_a | clk_core_200_800men_apb_z;

  assign clk_aud_12288k_update = ({clk_aud_12288k_count, 1'b1} == next_count);

  // Generate aclk from register ratio
  always@(posedge int_clk_i or negedge cgen_reset) begin
    if (!cgen_reset)
      clk_aud_12288k_count <= 1'b0;
    else if (clk_aud_12288k_update)
      clk_aud_12288k_count <= next_count[8:1] + clk_aud_12288k_ratio;
    else if (reg_clk_aud_12288k_wr)
      //Load with the next alligned count value
      clk_aud_12288k_count <= count[8:1] + clk_aud_12288k_count_next + pwdata[15:8];
  end

  assign clk_aud_12288k_count_next = clk_aud_12288k_ratio_in - (count[8:1] % clk_aud_12288k_ratio_in);

  //Create ENABLE to divide CLK
  always@(posedge clk_aud_12288kclk_int or negedge cgen_reset) begin
    if (!cgen_reset)
      clk_aud_12288k_en_count <= 8'b1;
    else if ((clk_aud_12288k_en_count == clk_aud_12288k_en_ratio) || (clk_aud_12288k_en_ratio == 8'b1))
      clk_aud_12288k_en_count <= 8'b1;
    else if (clk_aud_12288k_en_ratio != 8'b1)
      clk_aud_12288k_en_count <= clk_aud_12288k_en_count + 8'b1;
  end

  assign clk_aud_12288k_offset_diff = {8{reg_clk_aud_12288k_wr}} & (pwdata[15:8] - reg_clk_aud_12288k[15:8]);

  assign clk_aud_12288k_ratio = (|reg_clk_aud_12288k[7:0]) ? reg_clk_aud_12288k[7:0] : 8'b00000001;
  assign clk_aud_12288k_ratio_in = (|pwdata[7:0]) ? pwdata[7:0] : 8'b00000001;
  assign clk_aud_12288k_en_ratio = (|reg_clk_aud_12288k[25:18]) ? reg_clk_aud_12288k[25:18] : 8'b00000001;
  assign #2 clk_aud_12288k_up_del = clk_aud_12288k_update;
  assign clk_aud_12288k_up_or = clk_aud_12288k_update | clk_aud_12288k_up_del;
  assign clk_aud_12288ken = clk_aud_12288k_up_or;
  assign clk_aud_12288ken_del = clk_aud_12288k_up_del;
  assign clk_aud_12288ken_apb_a = (clk_aud_12288k_en_count == clk_aud_12288k_en_ratio) & clk_aud_12288k_update;
  assign #2 clk_aud_12288ken_apb_z = clk_aud_12288ken_apb_a;
  assign clk_aud_12288ken_apb = clk_aud_12288ken_apb_a | clk_aud_12288ken_apb_z;


endmodule

// --================================== End ==================================--
